/**
 * edurender
 * FullScreenQuad.cpp
 * (c) 2009 J. Brad Byrd
 */

#include "FullScreenQuad.h"

er::FullScreenQuad *er::FullScreenQuad::Create(ID3D10Device *device)
{
	FullScreenQuad *quad = new FullScreenQuad(device);
	
	if (!quad->Initialize())
	{
		delete quad;
		quad = 0;
	}
	
	return quad;
}

void er::FullScreenQuad::Destroy(er::FullScreenQuad *quad)
{
	delete quad;
}

void er::FullScreenQuad::SetTexture(ID3D10Texture2D *texture)
{
	if (texture == m_texture)
		return;

	SAFE_RELEASE(m_texture);
	SAFE_RELEASE(m_srv);		
		
	m_texture = texture;
	m_texture->AddRef();

	D3D10_TEXTURE2D_DESC td;
	texture->GetDesc(&td);

	D3D10_SHADER_RESOURCE_VIEW_DESC srvd;
	srvd.Format = td.Format;
	srvd.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
	srvd.Texture2D.MostDetailedMip = 0;
	srvd.Texture2D.MipLevels = td.MipLevels;
	
	m_device->CreateShaderResourceView(texture, &srvd, &m_srv);
}

void er::FullScreenQuad::Draw()
{
	UINT size = sizeof(Vertex);
	UINT offset = 0;
	m_device->IASetInputLayout(m_layout);
	m_device->IASetVertexBuffers(0, 1, &m_vb, &size, &offset);
	m_device->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
		
	if (m_srv)
		m_effect->GetVariableByName("g_texture")->AsShaderResource()->SetResource(m_srv);
	
	m_effect->GetTechniqueByIndex(0)->GetPassByIndex(0)->Apply(0);

	m_device->Draw(4, 0);
}

er::FullScreenQuad::FullScreenQuad(ID3D10Device *device) :
	m_device(device),
	m_vb(0),
	m_effect(0),
	m_layout(0),
	m_texture(0),
	m_srv(0)
{
	m_device->AddRef();
}

er::FullScreenQuad::~FullScreenQuad()
{
	SAFE_RELEASE(m_device);
	SAFE_RELEASE(m_vb);
	SAFE_RELEASE(m_effect);
	SAFE_RELEASE(m_layout);
	SAFE_RELEASE(m_texture);
	SAFE_RELEASE(m_srv);
}

bool er::FullScreenQuad::Initialize()
{
	Vertex vertices[] =
	{
		{ D3DXVECTOR2(-1.0f, -1.0f), D3DXVECTOR2(0.0f, 1.0f) },
		{ D3DXVECTOR2(-1.0f,  1.0f), D3DXVECTOR2(0.0f, 0.0f) },
		{ D3DXVECTOR2( 1.0f, -1.0f), D3DXVECTOR2(1.0f, 1.0f) },
		{ D3DXVECTOR2( 1.0f,  1.0f), D3DXVECTOR2(1.0f, 0.0f) },
	};
	
	D3D10_BUFFER_DESC bd;
	bd.ByteWidth = sizeof(Vertex) * 4;
	bd.Usage = D3D10_USAGE_IMMUTABLE;
	bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
	bd.CPUAccessFlags = 0;
	bd.MiscFlags = 0;
	
	D3D10_SUBRESOURCE_DATA srd;
	srd.pSysMem = vertices;
	srd.SysMemPitch = 0;
	srd.SysMemSlicePitch = 0;

	if (!SUCCEEDED(m_device->CreateBuffer(&bd, &srd, &m_vb)))
		return false;

	ID3D10Blob *blob = 0;
	HRESULT hr = ::D3DX10CreateEffectFromFile(L"FullScreenQuad.fx", NULL, NULL, "fx_4_0", 0, 0,
		m_device, NULL, NULL, &m_effect, &blob, NULL);

	if (!SUCCEEDED(hr))
	{
		if (blob != 0)
		{
			MessageBoxA(NULL, static_cast<LPCSTR>(blob->GetBufferPointer()), "Blarg!", 0);
			blob->Release();
		}
		
		return false;
	}
	
	D3D10_INPUT_ELEMENT_DESC layout[] = 
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D10_APPEND_ALIGNED_ELEMENT, D3D10_INPUT_PER_VERTEX_DATA, 0 },
		{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D10_APPEND_ALIGNED_ELEMENT, D3D10_INPUT_PER_VERTEX_DATA, 0 },
	};
	
	D3D10_PASS_DESC pd;
	m_effect->GetTechniqueByIndex(0)->GetPassByIndex(0)->GetDesc(&pd);
	hr = m_device->CreateInputLayout(layout, sizeof(layout) / sizeof(layout[0]), pd.pIAInputSignature, pd.IAInputSignatureSize, &m_layout);

	if (!SUCCEEDED(hr))
		return false;

	return true;
}
